package com.jewaton.auth.commons.util;


import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;

import java.sql.SQLException;
import java.util.List;

/**
 * 动态条件分页查询类
 * 
 * 
 */
@SuppressWarnings("all")
public class PageQueryHibernateCallback implements HibernateCallback {
	
	private static Logger logger = Logger.getLogger(PageQueryHibernateCallback.class.getName());
	
	private final int startingIndex;

	private final int pageSize;

	private final List<Criterion> criterionList;

	private final List<Order> orderList;

	private final Class queryClass;

	public PageQueryHibernateCallback(int startingIndex, int pageSize,
			List<Criterion> criterionList, List<Order> orderList,
			Class queryClass) {
		this.startingIndex = startingIndex;
		this.pageSize = pageSize;
		this.criterionList = criterionList;
		this.orderList = orderList;
		this.queryClass = queryClass;
	}

	public Object doInHibernate(Session session) throws HibernateException,
			SQLException {
		PagedQueryResult pagedQueryResult = new PagedQueryResult();

		Criteria criteria = session.createCriteria(queryClass);
		addCriterion(criteria);
		addSortBy(criteria);
		addRange(criteria);
		pagedQueryResult.setResults(criteria.list());

		Criteria criteriaCount = session.createCriteria(queryClass);
		addCriterion(criteriaCount);
		criteriaCount.setProjection(Projections.rowCount());
		int size = 0;
		if(criteriaCount.list().size()!=0){
			size = Integer.parseInt(criteriaCount.list().get(0).toString());
		}
		
		int maxPage = size % pageSize != 0 ? size / pageSize + 1 : size
				/ pageSize;
		pagedQueryResult.setMaxPage(maxPage);

		pagedQueryResult.setCurrentPage(startingIndex);
		pagedQueryResult.setPrePage(startingIndex == 1 ? startingIndex
				: startingIndex - 1);
		pagedQueryResult.setNextPage(startingIndex == maxPage ? maxPage
				: startingIndex + 1);
		return pagedQueryResult;
	}

	private void addRange(Criteria criteria) {
		criteria.setFirstResult((startingIndex - 1) * pageSize);
		criteria.setMaxResults(pageSize);
	}

	public void addCriterion(Criteria criteria) throws HibernateException {
		if (criterionList != null) {
			for (Criterion criterion : criterionList) {
				criteria.add(criterion);
			}
		}
	}

	private void addSortBy(Criteria criteria) {
		if (orderList != null) {
			for (Order order : orderList) {
				criteria.addOrder(order);
			}
		}
	}
}
